home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 March / macformat-022.iso / Shareware City / Developers / NeoIntroPP3.0 folder / PowerPlant / NeoBench / Source / CIDIndex.cp < prev    next >
Encoding:
Text File  |  1994-09-16  |  8.6 KB  |  290 lines  |  [TEXT/KAHL]

  1. /************************************************************
  2.  *
  3.  *    Created: Sunday, January 20, 1991 4:11:08 PM
  4.  *    CIDIndex.cp
  5.  *    C++ class implementation for ID-based index objects
  6.  *
  7.  *
  8.  *    Copyright Neologic Systems 1992
  9.  *    All rights reserved
  10.  *
  11.  *
  12.  * Within a class, references to permanent objects are kept in a sorted list called an
  13.  * index. The default sorting order in an index is ascending by ID value, however
  14.  * other sorting orders are possible. The class CIDIndex implements the default
  15.  * index.
  16.  *
  17.  ***********************************************************/
  18.  
  19. #include "NeoTypes.h"
  20. #include CNeoMetaClassH
  21. #include CNeoSelectH
  22. #include CNeoStreamH
  23. #include CNeoDatabaseH
  24. #include CNeoInodeH
  25. #include "CIDIndex.h"
  26. #include CNeoClassH
  27.  
  28. #ifndef NeoInherited
  29. #define NeoInherited    CNeoNode
  30. #endif
  31.  
  32. /* ****************************************************************** */
  33.                         /** Instance Methods **/
  34. /* ****************************************************************** */
  35.  
  36. #pragma segment NeoCreate
  37. CIDIndex::CIDIndex(const short aCount, CNeoNode *aParent, const NeoID aID)
  38.     : CNeoNode(aCount, TRUE, aParent)
  39. {
  40.     fID = aID;
  41. }
  42.  
  43. #ifdef qMacApp
  44. /*
  45.  * Apple's MPW compiler complains about not being able to automatically generate
  46.  * inline destructors. So we humor it to shut it up.
  47.  */
  48. #pragma segment NeoDestroy
  49. CIDIndex::~CIDIndex(void)
  50. {
  51. }
  52. #endif
  53.  
  54. /*
  55.  * Allocate and initialize a new instance.
  56.  */
  57. #pragma segment NeoCreate
  58. CNeoPersist *CIDIndex::New(void)
  59. {
  60.     CIDIndex *    object;
  61.  
  62.     object = new CIDIndex(0, nil, 0);
  63.  
  64.     return object;
  65. }
  66.  
  67. // Return the class ID for this kind of object
  68. #pragma segment NeoInfo
  69. NeoID CIDIndex::getClassID(void) const
  70. {
  71.     return kIDIndexID;
  72. }
  73.  
  74. /*
  75.  * This method returns the amount of file space the object occupies in the database.
  76.  */
  77. #pragma segment NeoInfo
  78. long CIDIndex::getFileLength(void) const
  79. {
  80.     return kIDIndexFileLength;
  81. }
  82.  
  83. /* ****************************************************************** */
  84.                         /** I/O Methods **/
  85. /* ****************************************************************** */
  86.  
  87. /*
  88.  * The readObject method is used to read in the permanent data members of the
  89.  * object from the given stream. In most cases, this method operates without concern
  90.  * for the type of stream the data values are coming from. As a result, this method
  91.  * is capable of reading from such diverse sources as the data fork of a file, a
  92.  * resource fork, an AppleEvent, the clipboard, a memory block, and so on.
  93.  *
  94.  * The aTag argument indicates how much information to read from the stream.
  95.  * It is sometimes sufficient to read in a minimum amount of data and have all
  96.  * other data be read in on demand. Other times it is necessary to read all the
  97.  * data immediately as the stream may not be available later.
  98.  *
  99.  * The two tag values that are currently used are kNeoObjectTag and kNeoAllTag.
  100.  *
  101.  * The value kNeoObjectTag means that only those values of immediate interest
  102.  * need to be read from the stream, though implementations of readObject may read
  103.  * in additional data member values if they wish.
  104.  *
  105.  * The value kNeoAllTag indicates that all data member values for this class
  106.  * should be read in to the stream.
  107.  */
  108. #pragma segment NeoRead
  109. void CIDIndex::readObject(CNeoStream *aStream, const NeoTag aTag)
  110. {
  111.     short    index;
  112.  
  113.     NeoInherited::readObject(aStream, aTag);
  114.  
  115.     for (index = 0; index < fCount; index++)
  116.         fEntry[index].fID = aStream->readLong();
  117. }
  118.  
  119. /*
  120.  * The writeObject method is used to write to the permanent data members of the
  121.  * object from the given stream. In most cases, this method operates without concern
  122.  * for the type of stream the data values are coming from. As a result, this method
  123.  * is capable of writing to such diverse sources as the data fork of a file, a
  124.  * resource fork, an AppleEvent, the clipboard, a memory block, and so on.
  125.  *
  126.  * The aTag argument indicates how much information to write to the stream.
  127.  * It is sometimes sufficient to write out only those parts that are dirty. Other
  128.  * times it is necessary to write all the data, as when doing Save As operation
  129.  * or when communicating an object's complete state across and RPC channel.
  130.  *
  131.  * The two tag values that are currently used are kNeoObjectTag and kNeoAllTag.
  132.  *
  133.  * The value kNeoObjectTag means that only those values of immediate interest
  134.  * need to be written to the stream, though implementations of writeObject may
  135.  * write out additional data member values if they wish.
  136.  *
  137.  * The value kNeoAllTag indicates that all data member values for this class
  138.  * should be writen out to the stream.
  139.  */
  140. #pragma segment NeoWrite
  141. void CIDIndex::writeObject(CNeoStream *aStream, const NeoTag aTag)
  142. {
  143.     short    index;
  144.  
  145.     NeoInherited::writeObject(aStream, aTag);
  146.  
  147.     for (index = 0; index < fCount; index++)
  148.         aStream->writeLong(fEntry[index].fID);
  149. }
  150.  
  151. /* ****************************************************************** */
  152.                 /** Object List Management Methods **/
  153. /* ****************************************************************** */
  154.  
  155.  
  156. /*
  157.  * The method getObject() reads in the object referred to by the specified entry.
  158.  * It allocates the object in memory then reads the object's state from the database.
  159.  */
  160. #pragma segment NeoSearch
  161. CNeoPersist *CIDIndex::getObject(const short aIndex)
  162. {
  163.     CNeoPersist *    object;
  164.     CNeoIDSelect    key(fEntry[aIndex].fID);
  165.  
  166.     object = (CNeoPersist *)CNeoClass::FindObject(CNeoMetaClass::FObjClassID, &key, FALSE, nil, nil);
  167.     object->unrefer();                // Our caller will add the reference if it wants to
  168.  
  169.     return object;
  170. }
  171.  
  172. /*
  173.  * The method insertObject() fills in the attributes of the new node entry and calls
  174.  * insertEntry() to add it in the proper place in the node.
  175.  */
  176. #pragma segment NeoAdd
  177. CNeoNode *CIDIndex::insertObject(const short aIndex, CNeoPersist *aObject)
  178. {
  179.     NeoID                oldClassID;
  180.     CNeoNode *            newRoot        = nil;
  181.     IDIndexEntry        newEntry;
  182.  
  183.     newEntry.fID = aObject->fID;
  184.  
  185.     oldClassID = CNeoMetaClass::FSysClassID;
  186.     CNeoMetaClass::FSysClassID = kIDIndexID;
  187.  
  188.     newRoot = insertEntry(aIndex, (Ptr)&newEntry);
  189.  
  190.     CNeoMetaClass::FSysClassID = oldClassID;
  191.  
  192. #ifdef qNeoDebug
  193.     if (newRoot)
  194.         NeoVerifyNode(newRoot);
  195.     else
  196.         NeoVerifyNode(this);
  197. #endif
  198.  
  199.     return newRoot;
  200. }
  201.  
  202. /*
  203.  * The KeyManager routine of a node class is a dispatch function. Dispatch functions
  204.  * are capable of performing more than one type of service. The first argument of the
  205.  * function indicates the type of service being requested.
  206.  *
  207.  * At a minimum, all KeyManager functions support the kNeoCanSupport and kNeoGetKey
  208.  * operations. The return value of a kNeoCanSupport request is a Boolean value
  209.  * indicating whether the node class can support a binary search using the given
  210.  * selection criterion. The return value of kNeoGetKey is a select key which can be
  211.  * used to locate the location of the given object in the btree.
  212.  *
  213.  * A pointer to a node class's KeyManager function is usually passed to the
  214.  * constructor of the node class's metaclass object. As such, the KeyManager function
  215.  * is usually called through the metaclass.
  216.  */
  217. #pragma segment NeoSearch
  218. void *CIDIndex::KeyManager(const NeoKeyOp aOp, ...)
  219. {
  220.     va_list            argptr;                    // pointer to argument list.
  221.     long            desperate;
  222.     NeoSelectType    selectType;
  223.     void *            value    = nil;
  224.     CNeoSelect *    key;
  225.     CNeoPersist *    object;
  226.  
  227.     va_start(argptr, aOp);
  228.     switch (aOp) {
  229.     case kNeoCanSupport:
  230.         key = va_arg(argptr, CNeoSelect *);
  231.         selectType = (key ? key->getSelectType() : pNeoID);
  232.         if (selectType == pNeoID)
  233.             value = (void *)(unsigned  char)TRUE;
  234. #ifdef qNeoShare
  235.         else if (selectType == kNeoAEKeySelect &&
  236.                  ((CNeoAEKeySelect *)key)->getAEKeyword() == pNeoID)
  237.             value = (void *)(unsigned  char)TRUE;
  238. #endif
  239.         else {
  240.             desperate = va_arg(argptr, long);
  241.             value = NeoInherited::KeyManager(kNeoCanSupport, key, desperate);
  242.         }
  243.         break;
  244.  
  245.     case kNeoGetKey:
  246.         object = va_arg(argptr, CNeoPersist *);
  247.         value = (void *)new CNeoIDSelect(object->fID);
  248.         break;
  249.     }
  250.     va_end(argptr);
  251.  
  252.     return value;
  253. }
  254.  
  255. /* ****************************************************************** */
  256.                 /** Entry Management Methods **/
  257. /* ****************************************************************** */
  258.  
  259. /*
  260.  * This virtual function provides a mechanism for determining the size of entries for
  261.  * a particular node.
  262.  */
  263. #pragma segment NeoInfo
  264. short CIDIndex::getEntrySize(void) const
  265. {
  266.     return sizeof(IDIndexEntry);
  267. }
  268.  
  269. #ifdef qNeoDebug
  270. /* ****************************************************************** */
  271.                         /** Debugging Methods **/
  272. /* ****************************************************************** */
  273. #pragma segment NeoDebug
  274. const void *CIDIndex::verify(const void *aValue) const
  275. {
  276.     short                    index;
  277.     const IDIndexEntry *    entry    = (IDIndexEntry *)aValue;
  278.  
  279.     for (index = 0; index < fCount; index++) {
  280.         if (entry)
  281.             entry->fID <= fEntry[index].fID;
  282.         entry = &fEntry[index];
  283.     }
  284.  
  285.     NeoInherited::verify(nil);
  286.  
  287.     return entry;
  288. }
  289. #endif
  290.